		TITLE	FORREF2 - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SEGMENTS

		PUBLIC	FORREF2,FORREF_COPY


		.DATA

		EXTERNDEF	FORREF_TEMP_RECORD:BYTE,FIX2_FH_XTRA:BYTE,FIX2_FH_TYPE:BYTE

		EXTERNDEF	EXETABLE:DWORD,FORREF_SIZE:DWORD,FORREF_ROUTINE:DWORD,FIX2_FIXUPP_EOR:DWORD,SRCADR:DWORD
		EXTERNDEF	FIX2_SM_START:DWORD,FIX2_STACK_DELTA:DWORD

		EXTERNDEF	MAJOR_MOVE_ROUTINE:DWORD


		.CODE	PASS2_TEXT

		EXTERNDEF	_err_abort:proc,CONVERT_SUBBX_TO_EAX:PROC,MOVE_LDATA_1:PROC,FORREF_MAJOR_MOVE:PROC,OBJ_PHASE:PROC
		EXTERNDEF	_abort:proc

		EXTERNDEF	FORREF_ERR:ABS

FOR_FAIL:
		MOV	AL,FORREF_ERR
		push	EAX
		call	_err_abort


FORREF2		PROC
		;
		;ESI IS FORREF RECORD
		;
		;FIRST SET SOME VARIABLES
		;
		XOR	EAX,EAX
		MOV	DL,FIX2_FH_TYPE

		MOV	MAJOR_MOVE_ROUTINE,OFF FORREF_COPY
		;
		;GET FORREF RECORD KIND...
		;
		MOV	AL,FIX2_FH_XTRA			;0, 1, 2
		MOV	ECX,FIX2_SM_START

		CMP	AL,3
		JNC	FOR_FAIL

		AND	EDX,MASK BIT_32
		JZ	L1$

		ADD	EAX,3
L1$:
		MOV	SRCADR,ECX

		MOV	ECX,FOR_TABLE[EAX*8+4]
		MOV	EAX,FOR_TABLE[EAX*8]

		MOV	FORREF_SIZE,ECX			;# OF BYTES IN TARGET
		MOV	FORREF_ROUTINE,EAX		;ROUTINE TO READ DATA
FOR_BYTES:
		MOV	EAX,[ESI]
		ADD	ESI,4

		TEST	EDX,EDX
		JNZ	FB_1

		AND	EAX,0FFFFH
		SUB	ESI,2
FB_1:
		;
		;USUALLY WE CAN UPDATE IN-PLACE...
		;
		;SAVE EDX
		;
		MOV	ECX,FIX2_STACK_DELTA
		MOV	EBX,FORREF_SIZE

		ADD	EAX,ECX
		;
		;SEE IF WE NEED LONG METHOD...
		;
		MOV	EDI,EAX
		AND	EAX,PAGE_SIZE-1

		ADD	EAX,EBX
		MOV	EBX,EDI

		CMP	EAX,PAGE_SIZE
		JA	FB_5
		;
		;
		;
		SHR	EBX,PAGE_BITS
		AND	EDI,PAGE_SIZE-1


		LEA	EBX,EXETABLE[EBX*4]
		CALL	CONVERT_SUBBX_TO_EAX

		ADD	EDI,EAX

		CALL	FORREF_ROUTINE
		;
		;
FB_9:
		CMP	FIX2_FIXUPP_EOR,ESI
		JA	FOR_BYTES

		JNZ	OBJ_E1

		RET

FB_5:
		PUSH	EDX
		MOV	EAX,EDI

		MOV	EDX,SRCADR
		SUB	EAX,ECX		;SUBTRACT STACK DELTA
		;
		PUSH	EDX
		ADD	EAX,EDX

		PUSH	ESI
		MOV	SRCADR,EAX
		;
		;HERE WE GO THRU A LOT OF GRIEF TO HANDLE WORST-CASE WHERE
		;BLOCK BOUNDARY IS CROSSED
		;
		;FIRST MOVE DATA TO KNOWN LOCATION
		;
		MOV	EAX,FORREF_SIZE
		XOR	ECX,ECX

		MOV	EDX,OFF FORREF_TEMP_RECORD

		CALL	FORREF_MAJOR_MOVE	;PUT IN FORREF_TEMP_RECORD

		POP	ESI
		MOV	EDI,OFF FORREF_TEMP_RECORD
		;
		;MODIFY DATA AT KNOWN LOCATION
		;
		CALL	FORREF_ROUTINE		;ADD IN BYTE

		;
		;NOW SET UP FOR MOVING DATA BACK OUT...
		;
		;NOW STORE NEW VALUE BACK OUT
		;
		MOV	EDX,SRCADR
		MOV	ECX,FORREF_SIZE

		MOV	EAX,OFF FORREF_TEMP_RECORD
		CALL	MOVE_LDATA_1		;DO IT...
		;
		;NOW, RESTORE STUFF
		;
		POPM	EAX,EDX

		MOV	SRCADR,EAX
		JMP	FB_9

OBJ_E1:
		CALL	OBJ_PHASE
		JMP	_abort

FORREF2		ENDP


FORREF_BYTE	PROC	NEAR
		;
		;
		MOV	AL,[ESI]
		MOV	CL,[EDI]

		ADD	AL,CL
		ADD	ESI,2

		MOV	[EDI],AL

		RET

FORREF_BYTE	ENDP


FORREF_BYTE_32	PROC

		MOV	AL,[ESI]
		MOV	CL,[EDI]

		ADD	AL,CL
		ADD	ESI,4

		MOV	[EDI],AL

		RET

FORREF_BYTE_32	ENDP


FORREF_WORD	PROC	NEAR
		;
		;
		;
		MOV	AX,[ESI]
		ADD	ESI,2

		ADD	[EDI],AX

		RET

FORREF_WORD	ENDP


FORREF_WORD_32	PROC	NEAR
		;
		;
		;
		MOV	AX,[ESI]
		ADD	ESI,4

		ADD	[EDI],AX

		RET

FORREF_WORD_32	ENDP


FORREF_DWORD	PROC	NEAR
		;
		;
		;
		XOR	EAX,EAX
		MOV	ECX,[EDI]

		MOV	AX,[ESI]
		ADD	ESI,4

		ADD	EAX,ECX

		MOV	[EDI],EAX

		RET

FORREF_DWORD	ENDP


FORREF_DWORD_32	PROC	NEAR
		;
		;
		;
		MOV	EAX,[ESI]
		MOV	ECX,[EDI]

		ADD	EAX,ECX
		ADD	ESI,4

		MOV	[EDI],EAX

		RET

FORREF_DWORD_32	ENDP


FORREF_COPY	PROC
		;
		;
		;
		;
		;EDX IS TARGET ADDRESS
		;ECX IS BYTE COUNT
		;EAX IS SOURCE ADDRESS
		;
		PUSHM	EDI,ESI

		MOV	ESI,EAX
		MOV	EDI,EDX

		REP	MOVSB

		POPM	ESI,EDI

		RET

FORREF_COPY	ENDP


		.CONST

		ALIGN	4

FOR_TABLE	DD	FORREF_BYTE,1
		DD	FORREF_WORD,2
		DD	FORREF_DWORD,4
		DD	FORREF_BYTE_32,1
		DD	FORREF_WORD_32,2
		DD	FORREF_DWORD_32,4


		END

